home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / netconf / html_access.c < prev    next >
C/C++ Source or Header  |  1996-08-03  |  7KB  |  298 lines

  1. /* #Specification: html mode / access limitation
  2.     We can specify the network or host which are allowed to access linuxconf
  3.     in web mode. We can simply define a set of network and netmask pairs.
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <netdb.h>
  10. #include "../misc/misc.h"
  11. #include "../dialog/dialog.h"
  12. #include "internal.h"
  13. #include "netconf.h"
  14. #include "netconf.m"
  15.  
  16. static NETCONF_HELP_FILE help_access ("html_access");
  17.  
  18. class HTML_ACCESS: public ARRAY_OBJ{
  19. public:
  20.     SSTRING net;
  21.     SSTRING mask;
  22.     unsigned long badr;
  23.     unsigned long bmask;
  24.     int err;    // Is this entry is valid (usable)
  25.     /*~PROTOBEG~ HTML_ACCESS */
  26. public:
  27.     HTML_ACCESS (const char *_net, const char *_mask);
  28.     /*~PROTOEND~ HTML_ACCESS */
  29. };
  30.  
  31. PUBLIC HTML_ACCESS::HTML_ACCESS(const char *_net, const char *_mask)
  32. {
  33.     net.setfrom (_net);
  34.     mask.setfrom (_mask);
  35.     err = 0;
  36.     badr = bmask = 0;
  37. }
  38.  
  39. class HTML_ACCESS_TB: public ARRAY{
  40.     /*~PROTOBEG~ HTML_ACCESS_TB */
  41. public:
  42.     HTML_ACCESS_TB (void);
  43. private:
  44.     void addfield (DIALOG&dia, HTML_ACCESS *a);
  45.     void addfields (DIALOG&dia);
  46. public:
  47.     int check (unsigned long badr);
  48.     int compute (char *errmsg);
  49.     void edit (void);
  50.     HTML_ACCESS *getitem (int no);
  51.     void setdefaults (void);
  52.     void write (void);
  53.     /*~PROTOEND~ HTML_ACCESS_TB */
  54. };
  55.  
  56. static const char HTMLACCESS[]="htmlaccess";
  57. static const char FROM[]="from";
  58.  
  59. PUBLIC HTML_ACCESS_TB::HTML_ACCESS_TB()
  60. {
  61.     SSTRINGS tb;
  62.     int n = linuxconf_getall (HTMLACCESS,FROM,tb,0);
  63.     for (int i=0; i<n; i++){
  64.         SSTRING *s = tb.getitem(i);
  65.         char net[200];
  66.         char mask[200];
  67.         mask[0] = '\0';
  68.         sscanf (s->get(),"%s %s",net,mask);
  69.         add (new HTML_ACCESS(net,mask));
  70.     }
  71. }
  72.  
  73. PUBLIC HTML_ACCESS *HTML_ACCESS_TB::getitem(int no)
  74. {
  75.     return (HTML_ACCESS *)ARRAY::getitem(no);
  76. }
  77.  
  78. PUBLIC void HTML_ACCESS_TB::write()
  79. {
  80.     int n=getnb();
  81.     linuxconf_removeall(HTMLACCESS,FROM);
  82.     for (int i=0; i<n; i++){
  83.         HTML_ACCESS *a = getitem(i);
  84.         if (!a->net.is_empty()){
  85.             char buf[400];
  86.             sprintf (buf,"%s %s",a->net.get(),a->mask.get());
  87.             linuxconf_add (HTMLACCESS,FROM,buf);
  88.         }
  89.     }
  90.     linuxconf_save();
  91. }
  92.  
  93. /*
  94.     Add one network to the dialog
  95. */
  96. PRIVATE void HTML_ACCESS_TB::addfield(DIALOG &dia, HTML_ACCESS *a)
  97. {
  98.     dia.newf_str (MSG_U(F_NETWORKHOST,"network or host"),a->net);
  99.     dia.newf_str (MSG_U(F_NETMASKOPT,"netmask(opt)"),a->mask);
  100. }
  101.  
  102. /*
  103.     Add two empty networks to the dialog
  104. */
  105. PRIVATE void HTML_ACCESS_TB::addfields(DIALOG &dia)
  106. {
  107.     for (int i=0; i<2; i++){
  108.         HTML_ACCESS *a = new HTML_ACCESS ("","");
  109.         add (a);
  110.         addfield (dia,a);
  111.     }
  112. }
  113. static HTML_ACCESS_TB *lookup;    // Use to speed up html_access_check
  114.                                 // avoiding reloading the struct all
  115.                                 // the time.
  116.  
  117. PUBLIC void HTML_ACCESS_TB::edit()
  118. {
  119.     DIALOG dia;
  120.     /* #Specification: html access / dialog / add button
  121.         The add button simply add few more empty lines at the
  122.         end of the dialog
  123.     */
  124.     int n=getnb();
  125.     for (int i=0; i<n; i++){
  126.         HTML_ACCESS *a = getitem(i);
  127.         addfield (dia,a);
  128.     }
  129.     addfields(dia);
  130.     dia.addwhat (MSG_U(F_EMPTYSLOT,"empty slots at the end of the dialog"));
  131.     int nof = 0;
  132.     while (1){
  133.         MENU_STATUS code = dia.edit (
  134.             MSG_U(T_HTMLACCESS,"Linuxconf html access control")
  135.             ,MSG_U(I_HTMLACCESS
  136.                 ,"You can specify which networks or hosts are allowed\n"
  137.                  "to access linuxconf to configure your computer\n"
  138.                  "(They need a password still)\n")
  139.             ,help_access
  140.             ,nof
  141.             ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_ADD);
  142.         char errmsg[10000];
  143.         if (code == MENU_CANCEL || code == MENU_ESCAPE){
  144.             break;
  145.         }else if (code == MENU_ADD){
  146.             addfields(dia);
  147.         }else if (compute(errmsg)==-1){
  148.             xconf_error ("%s",errmsg);
  149.         }else{
  150.             delete lookup;
  151.             lookup = NULL;
  152.             write();
  153.             break;
  154.         }
  155.     }
  156. }
  157.  
  158. void html_access_edit()
  159. {
  160.     HTML_ACCESS_TB htb;
  161.     htb.edit ();
  162. }
  163.                  
  164. /*
  165.     To speed up peer lookup, we walk the list of hosts/networks allowed
  166.     and resolved the addresses and netmask
  167.  
  168.     This function is also used to validate the dialog inputs.
  169.  
  170.     Return -1 if any error in the data.
  171. */
  172. PUBLIC int HTML_ACCESS_TB::compute(char *errmsg)
  173. {
  174.     errmsg[0] = '\0';
  175.     int ret = 0;
  176.     int n = getnb();
  177.     for (int i=0; i<n; i++){
  178.         HTML_ACCESS *a = getitem(i);
  179.         a->err = 0;
  180.         const char *net = a->net.get();
  181.         if (net[0] != '\0'){
  182.             /* #Specification: html access / host or net spec
  183.                 We can use the following things to specify a network or
  184.                 host access. A default suitable netmask is computed
  185.                 and is used unless one is supplied in the dialog.
  186.  
  187.                 #
  188.                 -An IP number
  189.                 -A host name
  190.                 -A network name
  191.                 -A device name (eth0). In this case the spec will be
  192.                  extracted
  193.                 #
  194.             */
  195.             char ipstr[16],mskstr[16];
  196.             if (ipfwrule_convert (net,ipstr,mskstr)==-1){
  197.                 ret = -1;
  198.                 a->err = 1;
  199.                 errmsg += sprintf (errmsg
  200.                     ,MSG_U(E_IVLDHOSTNET,"invalid host or network: %s\n")
  201.                     ,net);
  202.             }else{
  203.                 int n[4];
  204.                 device_aip24(ipstr,n);
  205.                 a->badr = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3];
  206.                 const char *msk = a->mask.get();
  207.                 if (msk[0] == '\0') msk = mskstr;
  208.                 if (device_aip24(msk,n)!=-1){
  209.                     a->bmask = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3];
  210.                 }else{
  211.                     ret = -1;
  212.                     a->err = 1;
  213.                     errmsg += sprintf (errmsg
  214.                         ,MSG_U(E_IVLDMASK,"invalid netmask: %s\n")
  215.                         ,msk);
  216.                 }
  217.             }
  218.             /* #Specification: html access / using a host to spec a net
  219.                 One can use a host to specify a network by using the
  220.                 proper netmask. This allows one to say "I accept all
  221.                 machine of the same network as this one".
  222.             */
  223.             a->badr &= a->bmask;
  224.         }
  225.     }
  226.     return ret;
  227. }
  228.  
  229. /*
  230.     Tell if one host address is acceptable (in this list)
  231.     Return -1 if not
  232. */
  233. PUBLIC int HTML_ACCESS_TB::check(unsigned long badr)
  234. {
  235.     int ret = -1;
  236.     int n = getnb();
  237.     for (int i=0; i<n; i++){
  238.         HTML_ACCESS *a = getitem(i);
  239.         if (!a->err){
  240.             if (a->badr==(badr & a->bmask)){
  241.                 ret = 0;
  242.             }
  243.         }
  244.     }
  245.     return ret;
  246. }
  247.  
  248. /*
  249.     Record default rules when noone are defined
  250.     See the spec at the top of this file
  251. */
  252. PUBLIC void HTML_ACCESS_TB::setdefaults()
  253. {
  254.     /* #Specification: html mode / access limitation / default rule
  255.         The default behavior is to accept connection originating from
  256.         the eth0 network only and the localhost.
  257.  
  258.         Once one rule is entered, the default is gone, even the loopback won't
  259.         be accepted.
  260.     */
  261.     if (getnb()==0){
  262.         // Set the default behavior
  263.         add (new HTML_ACCESS("127.0.0.1","255.255.255.255"));
  264.         HOSTINFO info;
  265.         if (netconf_loadinfos(info)!=-1){
  266.             const char *ipadr = info.a[0].ipaddr.get();
  267.             char stdmask[16];
  268.             const char *mask = info.a[0].netmask.get();
  269.             if (mask[0] == '\0'){
  270.                 mask = stdmask;
  271.                 char stdnet[16];
  272.                 device_setstdnetmask(ipadr,stdnet,stdmask);
  273.             }
  274.             add (new HTML_ACCESS(ipadr,mask));
  275.         }
  276.     }
  277. }
  278. /*
  279.     Check if a socket connection is coming from an accepted host
  280.     Return 0 if the "client" is allowed, -1 if not.
  281. */
  282. int html_access_check (int fd)
  283. {
  284.     int ret = -1;
  285.     struct sockaddr_in adr;
  286.     int len = sizeof(adr);
  287.     if (getpeername (fd,(struct sockaddr*)&adr,&len) != -1){
  288.         if (lookup == NULL){
  289.             lookup = new HTML_ACCESS_TB;
  290.             lookup->setdefaults();
  291.             char errmsg[10000];
  292.             lookup->compute(errmsg);
  293.         }
  294.         ret = lookup->check(ntohl(adr.sin_addr.s_addr));
  295.     }
  296.     return ret;
  297. }
  298.